#include "qusermanagerview.h"

#include "qadduserdialog.h"


#include "../../libs/sharedlib/qprojectcore.h"
#include "../../libs/sharedlib/qprojecthost.h"
#include "../../libs/corelib/styledbar.h"
#include "../../libs/corelib/qactiontoolbar.h"
#include "../../libs/corelib/qsoftcore.h"
#include "../../libs/sharedlib/qusermanager.h"
#include "../../libs/sharedlib/qnamevalidator.h"
#include "../../libs/coreLib/qundocommand/qcommandobject.h"
#include "../../libs/coreLib/qundocommand/qabstractundocommand.h"
#include "../../libs/sharedLib/qcommonstruct.h"


#include <QVBoxLayout>
#include <QHeaderView>
#include <QAction>
#include <QLabel>
#include <QPainter>
#include <QApplication>
#include <QSpinBox>
#include <QKeyEvent>

QWidget *QUserDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
{
    QWidget *ret=NULL;
    if(index.column()==1)
    {
        SHAREDLIB::QNameEdit *edit=new SHAREDLIB::QNameEdit("(.*)",parent);
        edit->setValue(index.data().toString());
        SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
        SHAREDLIB::QUserManager *manager=core->userManager();
        QStringList list;
        for(int i=0;i<manager->userCount();i++)
        {
            list.append(manager->getUser(i)->property("userName").toString());
        }
        list.removeAll(index.data().toString());
        edit->setIntermediateList(list);
        edit->setFrame(false);
        ret=edit;
    }
    else if(index.column()==3)
    {
        QSpinBox *s=new QSpinBox(parent);
        s->setRange(0,999999);
        s->setValue(index.data().toInt());
        ret=s;
    }
    else if(index.column()==2)
    {
        QLineEdit *e=new QLineEdit(parent);
        e->setFrame(false);
        ret=e;
    }
    else if(index.column()==4)
    {
        ret=new QLineEdit(parent);
        ((QLineEdit*)ret)->setFrame(false);
    }
    if(ret!=NULL)
    {
        ret->setProperty("no-ManhattanStyle",true);
    }
    return ret;
}

void QUserDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect.adjusted(0,0,0,-1));
}

QSize QUserDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize size=QItemDelegate::sizeHint(option,index);
    size.setHeight(21);
    return size;
}

void QUserDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QString str=model->index(index.row(),1).data().toString();
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    QObject *obj=core->userManager()->getUser(str);
    QItemDelegate::setModelData(editor,model,index);
    QModelIndex m=model->index(index.row(),index.column());
    if(obj!=NULL)
    {
        QString old;
        QString property_name;
        QString now=m.data().toString();
        if(index.column()==1)
        {
            property_name="userName";
        }
        else if(index.column()==3)
        {
            property_name="level";
        }
        else if(index.column()==2)
        {
            property_name="passWord";
        }
        else if(index.column()==4)
        {
            property_name="explanation";
        }

        old=obj->property(property_name.toLocal8Bit()).toString();
        if(old!=now)
        {
            emit m_view->need_make_page_position();
            QMap<QString,QVariant> param;
            param.insert("user",obj->property("userName"));
            param.insert("new_value",m.data().toString());
            param.insert("column",index.column());
            param.insert("old_value",old);
            param.insert("property_name",property_name);
            tagPagePositionInfo info=m_view->m_page_position.value<tagPagePositionInfo>();
            info.m_data.insert("QUserManagerView::select",index.row());
            QVariant v;
            v.setValue<tagPagePositionInfo>(info);
            param.insert("page_position",v);
            CORELIB::QAbstractUndoCommand* cmd=new CORELIB::QAbstractUndoCommand(param);

            if(index.column()==1)
            {
                connect(cmd->object(),SIGNAL(redo()),m_view,SLOT(cammand_rename()));
                connect(cmd->object(),SIGNAL(undo()),m_view,SLOT(cammand_rename()));
            }
            else
            {
                connect(cmd->object(),SIGNAL(redo()),m_view,SLOT(cammand_property()));
                connect(cmd->object(),SIGNAL(undo()),m_view,SLOT(cammand_property()));
            }

            CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
        }
    }
}

void QUserDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItemV3 opt=option;

    QColor c=QColor(255,255,191);

    if(opt.features & QStyleOptionViewItemV2::Alternate)
    {
        c=c.lighter(112);
    }
    painter->fillRect(option.rect,c);
    opt.state &=~ QStyle::State_HasFocus;
    QItemDelegate::paint(painter,opt,index);
    opt.palette.setCurrentColorGroup(QPalette::Active);
    QColor color=static_cast<QRgb>(qApp->style()->styleHint(QStyle::SH_Table_GridLineColor,&opt));
    painter->setPen(color);

    int right=option.direction==Qt::LeftToRight?option.rect.right():option.rect.left();
    painter->drawLine(right,option.rect.y(),right,option.rect.bottom());

    painter->drawLine(option.rect.left(),option.rect.bottom(),option.rect.right(),option.rect.bottom());
}


QUserManagerView::QUserManagerView(QWidget *parent) :
    QWidget(parent),
    m_userList(new QTreeWidget),
    m_styledBar(new CORELIB::StyledBar)
{

    QVBoxLayout *l=new QVBoxLayout;
    l->setMargin(0);
    l->setSpacing(0);
    l->addWidget(m_styledBar);
    l->addWidget(m_userList);

    this->setLayout(l);

    m_userList->setFrameStyle(QFrame::NoFrame);

    QStringList list;
    list<<tr("No.")<<tr("User Name")<<tr("Password")<<tr("User Level")<<tr("Explanation");
    m_userList->setHeaderLabels(list);
    m_userList->setAlternatingRowColors(true);
    m_userList->setEditTriggers(QAbstractItemView::EditKeyPressed);
    m_userList->setRootIsDecorated(false);
    m_userList->header()->setMovable(false);
    m_userList->setItemDelegate(new QUserDelegate(this));
    m_userList->setColumnWidth(0,100);
    m_userList->installEventFilter(this);

    CORELIB::QActionToolBar* toolbar=new CORELIB::QActionToolBar(Qt::AlignRight);
    l=new QVBoxLayout;
    l->setMargin(0);
    l->setSpacing(5);
    l->addWidget(toolbar);
    m_styledBar->setLayout(l);

    CORELIB::QSoftCore *core=CORELIB::QSoftCore::getCore();

    QAction *ac;
    QList<QAction*> aclist;

    ac=new QAction(this);
    ac->setSeparator(true);
    aclist.append(ac);

    ac=core->action("UserManager-Add");
    if(ac!=NULL)
    {
        connect(ac,SIGNAL(triggered()),this,SLOT(addUser()));
        aclist.append(ac);
    }

    ac=core->action("UserManager-Del");
    if(ac!=NULL)
    {
        connect(ac,SIGNAL(triggered()),this,SLOT(delUser()));
        aclist.append(ac);
    }

    ac=new QAction(this);
    ac->setSeparator(true);
    aclist.append(ac);

    toolbar->addButtonActions(aclist);

    QLabel *label=new QLabel;
    label->setText(tr("User Manager"));
    label->setStyleSheet("color:rgb(255,255,255);");
    toolbar->setLabelWidget(label);
    connect(m_userList,SIGNAL(clicked(QModelIndex)),m_userList,SLOT(edit(QModelIndex)));

    SHAREDLIB::QProjectCore *c=SHAREDLIB::QProjectCore::getCore();

    connect(c,SIGNAL(projectOpen()),this,SLOT(load()));
    connect(c,SIGNAL(projectClosed()),this,SLOT(clear()));

    QPalette p=m_userList->palette();
    p.setColor(QPalette::Inactive,QPalette::Highlight,p.color(QPalette::Active,QPalette::Highlight));
    p.setColor(QPalette::Inactive,QPalette::HighlightedText,p.color(QPalette::Active,QPalette::HighlightedText));
    m_userList->setPalette(p);
}

void QUserManagerView::addUser()
{
    QAddUserDialog dlg(this);
    dlg.exec();
    QString name=dlg.getName();
    if(name!="")
    {
        emit need_make_page_position();
        QMap<QString,QVariant> param;
        param.insert("name",name);
        param.insert("password",dlg.getPassword());
        param.insert("level",dlg.getLevel());
        param.insert("index",m_items.keys().size());
        tagPagePositionInfo info=m_page_position.value<tagPagePositionInfo>();
        info.m_data.insert("QUserManagerView::select",m_items.keys().size());
        QVariant v;
        v.setValue<tagPagePositionInfo>(info);
        param.insert("page_position",v);
        CORELIB::QAbstractUndoCommand *cmd=new CORELIB::QAbstractUndoCommand(param);
        connect(cmd->object(),SIGNAL(redo()),this,SLOT(cammand_add()));
        connect(cmd->object(),SIGNAL(undo()),this,SLOT(cammand_remove()));
        CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
    }
}

void QUserManagerView::addUserItem(QObject *obj)
{
    if(obj==NULL)
    {
        return;
    }
    QTreeWidgetItem* item=new QTreeWidgetItem(m_userList);
    m_items.insert(obj,item);
    item->setText(0,QString::number(m_userList->indexOfTopLevelItem(item)+1));
    item->setText(1,obj->property("userName").toString());
    item->setText(2,obj->property("passWord").toString());
    item->setText(3,obj->property("level").toString());
    item->setText(4,obj->property("explanation").toString());
    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
}

void QUserManagerView::insertUserItem(QObject *obj,int index)
{
    if(obj==NULL)
    {
        return;
    }
    QTreeWidgetItem* item=new QTreeWidgetItem(NULL);
    m_userList->insertTopLevelItem(index,item);
    m_items.insert(obj,item);
    item->setText(0,QString::number(m_userList->indexOfTopLevelItem(item)+1));
    item->setText(1,obj->property("userName").toString());
    item->setText(2,obj->property("passWord").toString());
    item->setText(3,obj->property("level").toString());
    item->setText(4,obj->property("explanation").toString());
    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable);
}

void QUserManagerView::delUser()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.value()->isSelected())
        {
            emit need_make_page_position();
            QMap<QString,QVariant>  param;
            param.insert("name",it.key()->property("userName"));
            param.insert("password",it.key()->property("passWord"));
            param.insert("level",it.key()->property("level"));
            param.insert("explanation",it.key()->property("explanation"));
            param.insert("index",m_userList->indexOfTopLevelItem(it.value()));
            tagPagePositionInfo info=m_page_position.value<tagPagePositionInfo>();
            info.m_data.insert("QUserManagerView::select",m_userList->indexOfTopLevelItem(it.value()));
            QVariant v;
            v.setValue<tagPagePositionInfo>(info);
            param.insert("page_position",v);
            CORELIB::QAbstractUndoCommand *cmd=new CORELIB::QAbstractUndoCommand(param);
            connect(cmd->object(),SIGNAL(redo()),this,SLOT(cammand_remove()));
            connect(cmd->object(),SIGNAL(undo()),this,SLOT(cammand_add()));
            CORELIB::QSoftCore::getCore()->get_undo_stack()->push(cmd);
            return;
        }
    }
}

void QUserManagerView::updateNo()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        it.value()->setText(0,QString::number(m_userList->indexOfTopLevelItem(it.value())+1));
    }
}

void QUserManagerView::itemUp()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.value()->isSelected())
        {
            SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
            int index=m_userList->indexOfTopLevelItem(it.value());
            if(index>0)
            {
                core->userManager()->swapUser(index,index-1);
                m_userList->takeTopLevelItem(index);
                m_userList->insertTopLevelItem(index-1,it.value());
                m_userList->clearSelection();
                it.value()->setSelected(true);
                updateNo();
            }
            return;
        }
    }
}

void QUserManagerView::itemDown()
{
    QMapIterator<QObject*,QTreeWidgetItem*> it(m_items);
    while(it.hasNext())
    {
        it.next();
        if(it.value()->isSelected())
        {
            SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
            int index=m_userList->indexOfTopLevelItem(it.value());
            if(index>=0 && index<m_items.size()-1)
            {
                core->userManager()->swapUser(index,index+1);
                m_userList->takeTopLevelItem(index);
                m_userList->insertTopLevelItem(index+1,it.value());
                m_userList->clearSelection();
                it.value()->setSelected(true);
                updateNo();
            }
            return;
        }
    }
}

void QUserManagerView::load()
{
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    SHAREDLIB::QUserManager *manager=core->userManager();

    int count=manager->userCount();
    for(int i=0;i<count;i++)
    {
        addUserItem(manager->getUser(i));
    }
    if(count>0)
    {
        m_userList->setCurrentIndex(m_userList->model()->index(0,0));
    }
}

void QUserManagerView::clear()
{
    m_items.clear();
    m_userList->clear();
}

void QUserManagerView::cammand_add()
{
    QObject* obj=sender();

    QString name=obj->property("name").toString();
    QString password=obj->property("password").toString();
    QString explanation=obj->property("explanation").toString();
    int level=obj->property("level").toInt();
    int index=obj->property("index").toInt();

    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    SHAREDLIB::QUserManager *manager=core->userManager();

    obj=manager->getUser(name);
    if(obj!=NULL)
    {
        return ;
    }

    obj=new QObject;
    obj->setProperty("userName",name);
    obj->setProperty("passWord",password);
    obj->setProperty("level",level);
    obj->setProperty("explanation",explanation);

    manager->inserUser(index,obj);
    insertUserItem(obj,index);
    m_userList->setCurrentItem(m_items.value(obj));
    updateNo();
}

void QUserManagerView::cammand_remove()
{
    QObject* obj=sender();

    QString name=obj->property("name").toString();
    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();
    SHAREDLIB::QUserManager *manager=core->userManager();

    obj=manager->getUser(name);
    if(obj!=NULL)
    {
        QTreeWidgetItem* item=m_items.value(obj);
        if(item!=NULL)
        {
            m_items.remove(obj);
            delete item;
        }
    }

    manager->removeUser(name);

    updateNo();
}

void QUserManagerView::cammand_rename()
{
    QString old=sender()->property("old_value").toString();
    QString now=sender()->property("new_value").toString();

    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();

    QObject* obj=core->userManager()->getUser(old);
    core->userManager()->setUserName(obj,now);

    QTreeWidgetItem* item=m_items.value(obj);
    item->setText(1,now);

    sender()->setProperty("old_value",now);
    sender()->setProperty("new_value",old);
}

void QUserManagerView::cammand_property()
{
    QString old=sender()->property("old_value").toString();
    QString now=sender()->property("new_value").toString();
    QString name=sender()->property("user").toString();
    int index=sender()->property("column").toInt();
    QString property_name=sender()->property("property_name").toString();

    SHAREDLIB::QProjectCore *core=SHAREDLIB::QProjectCore::getCore();

    QObject* obj=core->userManager()->getUser(name);
    obj->setProperty(property_name.toLocal8Bit(),now);

    QTreeWidgetItem* item=m_items.value(obj);
    item->setText(index,now);

    sender()->setProperty("old_value",now);
    sender()->setProperty("new_value",old);
}

void QUserManagerView::set_page_position(const QVariant &info)
{
    m_page_position=info;
}

void QUserManagerView::make_page_position(QVariant &info)
{
}

bool QUserManagerView::pagePosition(const QVariant &param)
{
    tagPagePositionInfo in=param.value<tagPagePositionInfo>();
    int index=in.m_data.value("QUserManagerView::select").toInt();
    if(index<m_items.values().size())
    {
        m_userList->setCurrentIndex(m_userList->model()->index(index,0));
    }
    return false;
}

bool QUserManagerView::eventFilter(QObject *o, QEvent *e)
{
    if(o==m_userList)
    {
        if(e->type()==QEvent::KeyPress)
        {
            QKeyEvent *event=(QKeyEvent*)e;
            if(event->key()==Qt::Key_Delete)
            {
                delUser();
                return true;
            }
        }
    }
    return false;
}
